package com.meta.nd.util;


import java.util.List;

import com.meta.common.ConstDef;
import com.meta.nd.vo.Fd;
import com.meta.nd.vo.Nd;
import com.meta.nd.vo.Nv;
import com.meta.nd.vo.Rd;

public class NvTool {
	private static Nd nd_nd = null;
	private static Nd ndDbMappingNd = null;
public static Nd getNdNd()
 {
	if ( nd_nd != null )
		return nd_nd;
	/***************创建Nd的结构**************/
	Nd ndNd = new Nd();
	ndNd.setNdCode(ConstDef.ND_CODE_ND);
	ndNd.setNdName(ConstDef.ND_NAME_ND);
	ndNd.setNdDescription("节点结构");
	ndNd.setMinCount(0);
	ndNd.setMaxCount(999);
	ndNd.setDbMapCode(ConstDef.ND_DB_MAPPING_ND);
	ndNd.setCursive(true);
	ndNd.setUpdateTime(NodeUtil.parseDatetime("2100-01-01 00:00:00"));
	ndNd.addFd( new Fd(ConstDef.FD_NAME_DB_MAP_CODE,"nd类型", ConstDef.DATA_TYPE_STRING));
	Fd fd = new Fd(ConstDef.FD_NAME_ND_CODE,"代码", ConstDef.DATA_TYPE_STRING);
	ndNd.addFd(fd);
	ndNd.addFd(new Fd(ConstDef.FD_NAME_ND_NAME,"nd名称", ConstDef.DATA_TYPE_STRING));
	ndNd.addFd(new Fd(ConstDef.FD_NAME_ND_ALIAS,"nd别名", ConstDef.DATA_TYPE_STRING));
	ndNd.addFd(new Fd(ConstDef.FD_NAME_ND_DESCRIPTION,"nd描述", ConstDef.DATA_TYPE_STRING));
	ndNd.addFd(new Fd(ConstDef.FD_NAME_META_CLASS_NAME,"元数据类名", ConstDef.DATA_TYPE_STRING));
	ndNd.addFd(new Fd(ConstDef.FD_NAME_NV_CLASS_NAME,"实例类名", ConstDef.DATA_TYPE_STRING));
	ndNd.addFd(new Fd(ConstDef.FD_NAME_SERVICE_CLASS_NAME,"服务类名", ConstDef.DATA_TYPE_STRING));
	 ndNd.addFd(new Fd(ConstDef.FD_NAME_CATEGORY,"分类", ConstDef.DATA_TYPE_STRING));
	ndNd.addFd(new Fd(ConstDef.FD_NAME_MIN_COUNT,"最小个数", ConstDef.DATA_TYPE_INT));
	ndNd.addFd(new Fd(ConstDef.FD_NAME_MAX_COUNT,"最大个数", ConstDef.DATA_TYPE_INT));
	ndNd.addFd(new Fd(ConstDef.FD_NAME_CURSIVE,"递归", ConstDef.DATA_TYPE_BOOLEAN));
	fd = new Fd(ConstDef.FD_NAME_UPDATE_TIME,"", ConstDef.DATA_TYPE_DATETIME);
	ndNd.addFd(fd);
	/**创建Fd结构**/
	Nd fdNd = new Nd();
	fdNd.setNdCode(ConstDef.ND_CODE_FD);
	fdNd.setNdName(ConstDef.ND_NAME_FD);
	fdNd.setNdDescription("fd结构");
	fdNd.setMinCount(0);
	fdNd.setMaxCount(999);
	fdNd.setDbMapCode(ConstDef.ND_DB_MAPPING_FD);
	fdNd.setUpdateTime(NodeUtil.parseDatetime("2100-01-01 00:00:00"));
	fd = new Fd("fdCode","fd代码", ConstDef.DATA_TYPE_STRING);
	fdNd.addFd(fd);
	fdNd.addFd( new Fd("fdName","fd名称", ConstDef.DATA_TYPE_STRING));
	fdNd.addFd( new Fd("fdDescription","fd描", ConstDef.DATA_TYPE_STRING));
	fdNd.addFd( new Fd("dataType","数据类型", ConstDef.DATA_TYPE_STRING));
	fdNd.addFd( fd );
	fdNd.addFd( new Fd("mdCode","主数据代码", ConstDef.DATA_TYPE_STRING));
	fdNd.addFd( new Fd("serNo","序号", ConstDef.DATA_TYPE_INT));
	ndNd.addChild(fdNd);
	 /**创建Rd结构**/
	Nd rdNd = new Nd();
	rdNd.setNdCode(ConstDef.ND_CODE_RD);
	rdNd.setNdName("rd");
	rdNd.setNdDescription("rd结构");
	rdNd.setMinCount(0);
	rdNd.setMaxCount(999);
	rdNd.setDbMapCode(ConstDef.ND_DB_MAPPING_RD);
	rdNd.setUpdateTime(NodeUtil.parseDatetime("2100-01-01 00:00:00"));
	fd = new Fd("rdCode","rd代码", ConstDef.DATA_TYPE_STRING);
	rdNd.addFd(fd);
	rdNd.addFd( new Fd("rdName","rd名称", ConstDef.DATA_TYPE_STRING));
	rdNd.addFd( new Fd("rdDescription","rd描述", ConstDef.DATA_TYPE_STRING));
	rdNd.addFd( new Fd("transactionType","交易类型", ConstDef.DATA_TYPE_STRING));
	rdNd.addFd( new Fd("orderType","顺序类型", ConstDef.DATA_TYPE_STRING));
	rdNd.addFd( new Fd("executeOrder","顺序类型", ConstDef.DATA_TYPE_INT));
	rdNd.addFd( new Fd("ruleText","规则文本", ConstDef.DATA_TYPE_STRING));
	ndNd.addChild(rdNd);
	nd_nd = ndNd;
	return ndNd;
}

	
public static NdDbMapping getNdNdDbMapping() {
	NdDbMapping mapping =   new NdDbMapping(ConstDef.ND_DB_MAPPING_ND,"T_Nd",null,"ndCode,ndName,ndAlias,ndDescription,metaClassName,nvClassName,serviceClassName,category,dbMapCode,minCount,maxCount,cursive,updateTime",null,false);
	mapping.setUpdateTime(NodeUtil.parseDatetime("2100-01-01 00:00:00"));
	return mapping;
}

public static NdDbMapping getFdNdDbMapping(){
	NdDbMapping mapping =  new NdDbMapping(ConstDef.ND_DB_MAPPING_FD,"T_FD",null,"fdCode,fdName,fdDescription,dataType,serNo,mdCode",null, false);
	mapping.setUpdateTime(NodeUtil.parseDatetime("2100-01-01 00:00:00"));
	return mapping;
}
public static NdDbMapping getRdNdDbMapping(){
	NdDbMapping mapping = new NdDbMapping(ConstDef.ND_DB_MAPPING_RD,"T_RD",null,"rdCode,rdName,rdDescription,transactionType,orderType,executeOrder,ruleText",null, false);
	mapping.setUpdateTime(NodeUtil.parseDatetime("2100-01-01 00:00:00"));
	return mapping;
}
	
public static Nd getNdDbMappingNd() {
	if (ndDbMappingNd != null)
		return ndDbMappingNd;
	Nd nd = new Nd();
	nd.setNdCode(ConstDef.ND_CODE_TYPE_MAPPING_ND);
	nd.setNdName("dbMapping");
	nd.setNdDescription("类型结构映射");
	nd.setMinCount(0);
	nd.setMaxCount(999);
	nd.setDbMapCode(ConstDef.ND_DB_MAPPING_DB_MAPPING);
	nd.setCursive(false);
	nd.setUpdateTime(NodeUtil.parseDatetime("2100-01-01 00:00:00"));
	nd.getFds().add( new Fd("name","类型", ConstDef.DATA_TYPE_STRING));
	nd.getFds().add( new Fd("description","查询语句", ConstDef.DATA_TYPE_STRING));
	nd.getFds().add( new Fd("dbMapCode","类型", ConstDef.DATA_TYPE_STRING));
	nd.getFds().add( new Fd("nvTableName","值表名称", ConstDef.DATA_TYPE_STRING));
	nd.getFds().add( new Fd("fvTableName","字段表名称", ConstDef.DATA_TYPE_STRING));
	nd.getFds().add( new Fd("nvFieldNames","值表的字段列表", ConstDef.DATA_TYPE_STRING));
	nd.getFds().add( new Fd("fvFieldNames","字段表的字段列表", ConstDef.DATA_TYPE_STRING));
	nd.getFds().add( new Fd("persistRemainFields","是否持久化剩余列表", ConstDef.DATA_TYPE_BOOLEAN));
	Fd fd = new Fd("updateTime","", ConstDef.DATA_TYPE_DATETIME);
	nd.getFds().add(fd);
	ndDbMappingNd = nd;
	return nd;
}
	
	
public static NdDbMapping getDbMappingMapping() {
	NdDbMapping mapping =  new NdDbMapping(ConstDef.ND_DB_MAPPING_DB_MAPPING,"T_NdMapping",null,"dbMapCode,name,description,nvTableName,fvTableName,nvFieldNames,fvFieldNames,persistRemainFields,updateTime",null,false);
	mapping.setUpdateTime(NodeUtil.parseDatetime("2100-01-01 00:00:00"));
	return mapping;
}

	
	
	public static Nd instance2Nd ( Nv nv  ) {
		
		nd_nd = getNdNd();
		
		Nd nd = new Nd();
		nd.setNdCode(nv.getRawStringByName("ndCode"));
		nd.setNdName(nv.getRawStringByName("ndName"));
		nd.setNdDescription(nv.getRawStringByName("ndDescription"));
		nd.setMinCount(nv.getRawIntByName("minCount"));
		nd.setMaxCount(nv.getRawIntByName("maxCount"));
		nd.setDbMapCode(nv.getRawStringByName("dbMapCode") );
		nd.setCursive(nv.getRawBoolByName("cursive"));
		nd.setUpdateTime(nv.getRawDateByName("updateTime"));		
		
		List<Nv> rdNvs = nv.getChildNvs("rd");
		
		if (rdNvs != null)		
			for ( Nv rdNv : rdNvs  ) {
				
				Rd rd = new Rd();			
				rd.setCode(rdNv.getRawStringByName("rdCode"));
				rd.setName(rdNv.getRawStringByName("rdName"));
				rd.setDescription(rdNv.getRawStringByName("rdDescription"));
				rd.setTransactionType(rdNv.getRawStringByName("businessType"));
				rd.setOrderType(rdNv.getRawStringByName("orderType"));
				rd.setExecuteOrder(rdNv.getRawIntByName("executeOrder"));
				nd.getRds().add(rd);
			}
		
		
		List<Nv> fdNvs = nv.getChildNvs("fd");
		
		if ( fdNvs != null )
			for ( Nv fdNv : fdNvs  ) {
				
				Fd fd = new Fd();
				
				fd.setFdCode(fdNv.getRawStringByName("fdCode"));
				fd.setFdName(fdNv.getRawStringByName("fdName"));
				fd.setFdDescription(fdNv.getRawStringByName("fdDescription"));
				fd.setDataType(fdNv.getRawStringByName("dataType"));
				//fd.setFdControl(fdNv.getRawStringByName("fdControl"));
				nd.getFds().add(fd);
				
			}
		
		
		
		List<Nv> childNdNvs = nv.getChildNvs( nd_nd.getNdName());
		if ( childNdNvs != null )
			for ( Nv childNdNv : childNdNvs ) {
				Nd childNd = instance2Nd(childNdNv);
				nd.addChild(childNd);
			}	
		
		return nd;
	}
	
	
	public static Nv nd2Instance ( Nd nd  ) {
		
		nd_nd = getNdNd();	
		Nv nv = NodeUtil.nd2Nv(nd_nd);
		
		nv.setStringFvByName("ndCode", nd.getNdCode());
		nv.setStringFvByName("ndName", nd.getNdName());
		nv.setStringFvByName("ndDescription", nd.getNdDescription());
		nv.setIntFvByName("minCount", nd.getMinCount());
		nv.setIntFvByName("maxCount", nd.getMaxCount());		
		nv.setStringFvByName("dbMapCode", nd.getDbMapCode());
		nv.setBoolFvByName("cursive", nd.isCursive());
		nv.setOperationFlag(ConstDef.OPERATION_FLAG_NEW);
		
		List<Fd> fds = nd.getFds();
		Nd fdNd = nd_nd.getChildNd("fd");
		
		for ( Fd fd : fds ) {
			Nv fdNv = NodeUtil.nd2Nv(fdNd);
			fdNv.setStringFvByName("fdCode", fd.getFdCode());
			fdNv.setStringFvByName("fdName", fd.getFdName());
			fdNv.setStringFvByName("fdDescription", fd.getFdDescription());
			fdNv.setStringFvByName("dataType", fd.getDataType());
			fdNv.setOperationFlag(ConstDef.OPERATION_FLAG_NEW);
			//fdNv.setStringFvByName("fdControl", fd.getFdControl());
			nv.addChildNv(fdNd.getNdName(), fdNv);
		}
		
		

		List<Rd> rds = nd.getRds();
		Nd rdNd = nd_nd.getChildNd("rd");
		for ( Rd rd : rds ) {
			Nv rdNv = NodeUtil.nd2Nv(rdNd);
			rdNv.setStringFvByName("rdCode", rd.getCode());
			rdNv.setStringFvByName("rdName", rd.getName());
			rdNv.setStringFvByName("rdDescription", rd.getDescription());
			rdNv.setStringFvByName("businessType", rd.getTransactionType());
			rdNv.setStringFvByName("orderType", rd.getOrderType());
			rdNv.setIntFvByName("executeOrder", rd.getExecuteOrder());
			rdNv.setOperationFlag(ConstDef.OPERATION_FLAG_NEW);
			nv.addChildNv(rdNd.getNdName(), rdNv);
		}	

		for ( Nd childNd : nd.getChildren() ) {
			Nv childNv = nd2Instance(childNd);
			nv.addChildNv(nd_nd.getNdName(), childNv);
		}
		
		return nv;
	}

	
	public static Nv ndTypeMapping2Nv ( NdDbMapping ndTypeMap ) {
		
		Nd nd = getNdDbMappingNd();
		Nv nv = NodeUtil.nd2Nv(nd);
		nv.setStringFvByName("dbMapCode", ndTypeMap.getDbMapCode());
		nv.setStringFvByName("name", ndTypeMap.getName());
		nv.setStringFvByName("description", ndTypeMap.getDescription());
		nv.setStringFvByName("selectSql", ndTypeMap.getSelectSql());
		nv.setStringFvByName("updateSql", ndTypeMap.getUpdateSql());
		nv.setStringFvByName("insertSql", ndTypeMap.getInsertSql());
		nv.setStringFvByName("nvTableName", ndTypeMap.getNvTableName());
		nv.setStringFvByName("fvTableName", ndTypeMap.getFvTableName());
		nv.setStringFvByName("nvFieldNames", mergeStringList(ndTypeMap.getNvFieldNames()));
		nv.setStringFvByName("fvFieldNames", mergeStringList(ndTypeMap.getFvFieldNames()));
		nv.setBoolFvByName("persistRemainFields", ndTypeMap.isPersistRemainFields());
		
		return nv;
		
	}
	
	private static String mergeStringList( List<String> strs ) {
		
		if (strs == null || strs.size() == 0)
			return null;
		
		StringBuffer sb = new StringBuffer();
		for( String s : strs )
		{ 
			sb.append(s.trim()+","); 
		} 
		
		String newStr = sb.toString();
		
		
		if ( newStr != null && newStr.length() > 1 )
			
			return newStr.substring(0, newStr.length() - 1);
		
		else 
			return null;
		
	}
	
	public static NdDbMapping nv2NdTypeMapping(Nv nv ) {
				
		NdDbMapping ndDbMapping = new NdDbMapping(
				nv.getRawStringByName("dbMapCode"),
				nv.getRawStringByName("nvTableName"),
				nv.getRawStringByName("fvTableName"),
				nv.getRawStringByName("nvFieldNames"),
				nv.getRawStringByName("fvFieldNames"),		
				nv.getRawBoolByName("persistRemainFields")
		);

		ndDbMapping.setName(nv.getRawStringByName("name"));
		ndDbMapping.setDescription(nv.getRawStringByName("description"));
		ndDbMapping.setUpdateTime(nv.getRawDateByName("updateTime"));
		
		return ndDbMapping;
	}

	public static void cursiveSetOperationFlagNew(Nv nv ){
		nv.setOperationFlag(ConstDef.OPERATION_FLAG_NEW);
		for( List<Nv> childNvs : nv.getChildrenMap().values()){
			for(Nv childNv : childNvs){
				cursiveSetOperationFlagNew(childNv);
			}
		}
	}

}
